<?php

class PikachuLogicComponent extends Object {

	const INIT_REFRESH = 7;
	const INIT_GAME_WIDTH = 16;
	const INIT_GAME_HEIGHT = 9;
	const INIT_GAME_STAGE_TIME = 630;
	const INIT_GAME_MAX_VALUE = 36;

	const ACTION_START_STAGE = 'startstage';
	const ACTION_REFRESH = 'refresh';
	const ACTION_MOVE = 'move';
	const ACTION_END_STAGE = 'endstage';
	const ACTION_CHECK_TOKEN = 'checktoken';

	protected $_params = array(
		'token' => 0,
		'refresh' => 0,
		'stage' => 0,
		'score' => 0,
		'stages' => array(
			// array
			//		score
			//		activities
			//			0 start data, time
			//			1 move { array of moves }
			//			2 refresh data, time
			//			3 end data, time
		),
	);

	public function setData($params){
		$this->_params = (array)$params;
	}

	public function getData(){
		return $this->_params;
	}

	public function checkToken($token){
		$data['valid'] = $token == $this->_params['token'];
		$this->_setActivity(self::ACTION_CHECK_TOKEN, $data);
		$this->_params['token'] = $this->_genToken();
	}

	public function newGame(){
		$this->_params['token'] = $this->_genToken();
		$this->_params['refresh'] = self::INIT_REFRESH;
		$this->_params['stage'] = 0;
		$this->_params['score'] = 0;
		$this->_params['scorea'] = 0;
		$this->_params['stages'] = array();
		$this->_params['refresh']--;
		$this->newStage();
	}

	public function newStage(){
		$this->_params['refresh']++ ;
		$this->_params['stage']++;
		$this->_params['scorea']  = 0;
		$stage = $this->_params['stage'];
		$this->_params['stages'][$stage]['time_begin'] = time();
		$this->_params['stages'][$stage]['time_end'] = 0;
		$this->_params['stages'][$stage]['time_paused'] = 0;
		$this->_params['stages'][$stage]['time_paused_begin'] = 0;
		$data['data'] = array();
		$this->_setActivity(self::ACTION_START_STAGE, $data);
	}

	public function setMoves($moves){
		foreach($moves as $move){
			if(empty($move)){
				continue;
			}
			$this->_params['score'] += 10;
			$this->_setActivity(self::ACTION_MOVE, $move);
		}
	}

	public function refresh(){
		$this->_params['refresh']--;
		$this->_setActivity(self::ACTION_REFRESH, array());
	}

	public function endStage($cleared = true){
		$stage = $this->_params['stage'];
		if(!empty($this->_params['stages'][$stage]['time_end'])){
			return; // stage ended
		}
		$end = $this->_params['stages'][$stage]['time_end'] = time();
		$start = $this->_params['stages'][$stage]['time_begin'];
		$paused = $this->_params['stages'][$stage]['time_paused'];
		$this->_params['stages'][$stage]['time_paused'] = 0; // clear paused time after end stage
		if(!$cleared){
			$rTime = 0;
		} else {
			$rTime = self::INIT_GAME_STAGE_TIME - ($end - $start) + $paused;
		}
		$addP = $rTime >= 0 ? $rTime : 5 * $rTime;
		$this->_params['scorea'] = $addP;
		$this->_params['score'] += $addP;
	}

	public function endGame($win = true){
		if($win){
			$this->endStage(true);
			$scoreAdded = $this->_params['refresh'] * 50;
			$this->_params['scorea'] += $scoreAdded;
			$this->_params['score'] += $scoreAdded;
		} else {
			$this->endStage(false);
		}
	}

	public function pause(){
		$stage = $this->_params['stage'];
		$this->_setActivity('pause', array());
		$this->_params['stages'][$stage]['time_paused_begin'] = time();
	}

	public function resume(){
		$stage = $this->_params['stage'];
		$this->_setActivity('resume', array());
		$this->_params['stages'][$stage]['time_paused'] += time() - $this->_params['stages'][$stage]['time_paused_begin'];
	}

	protected function _setActivity($name, $data){
		$stage = $this->_params['stage'];
		$data['action'] = $name;
		$data['time'] = time();
		$this->_params['stages'][$stage]['activities'][] = $data;
	}

	protected function _randValues($values = array()){
		if(empty($values)){
			$values = array();
			for($i = 1; $i<= $this->_gWidth * $this->gHeight; $i++){
				$val = $i % $this->_gMaxValue;
				if($val == 0){
					$val = $this->_gMaxValue;
				}
			}
		}
		return array_rand($values, count($values));
	}

	protected function _genToken(){
		return substr(sha1(uniqid()), 0, 10);
	}

	// database interaction group

	public function syncPlayer($data){
		Utils::loadModels($this, array('Pikachu.PikachuPlayer'));
		$player = $this->PikachuPlayer->findByEmail($data['PikachuPlayer']['email']);
		if(empty($player)){
			// try to create him
			$this->PikachuPlayer->saveIt($data, 'email');
			$player = $this->PikachuPlayer->findByEmail($data['PikachuPlayer']['email']);
		}
		return $player;
	}

	public function saveScore($data){
		Utils::loadModels($this, array('Pikachu.PikachuScore'));
		$data = array(
			'player_id' => $data['PikachuPlayer']['id'],
			'score' => $this->_params['score'],
			'log' => json_encode($this->_params)
		);
		$this->PikachuScore->saveIt($data);
	}
}